﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using PostSharp.Aspects;
using PostSharp.Extensibility;
using PostSharp.Aspects.Advices;
using PostSharp.Reflection;
using MonitoredUndo;
using System.Diagnostics;

namespace ToDoIt2.Aspects {
	[Serializable]
	[IntroduceInterface(typeof(ISupportsUndo), OverrideAction = InterfaceOverrideAction.Ignore)]
	[MulticastAttributeUsage(MulticastTargets.Class, Inheritance = MulticastInheritance.Strict)]
	public sealed class SupportsUndoAttribute  : InstanceLevelAspect, ISupportsUndo {
		[IntroduceMember(Visibility = Visibility.Family, OverrideAction = MemberOverrideAction.Ignore)]
		public object GetUndoRoot() { return (App.Current as App).DocumentVM;	}
	
		/// <summary>
		/// Method intercepting any call to a property setter.
		/// </summary>
		/// <param name="args">Aspect arguments.</param>
		[OnLocationSetValueAdvice, MulticastPointcut(Targets = MulticastTargets.Property, Attributes = MulticastAttributes.Instance)]
		public void OnPropertySet(LocationInterceptionArgs args) {
			// Don't go further if the new value is equal to the old one.
			// (Possibly use object.Equals here).
			if (args.Value == args.GetCurrentValue())
				return;

			// This line will log the property change with the undo framework.
			DefaultChangeFactory.OnChanging(this.Instance, args.Location.Name, args.GetCurrentValue(), args.Value);
			Debug.WriteLine(String.Format("DefaultChangeFactory.OnChanging(), Instance: {0}, Name: {1}, {2} -> {3}", this.Instance, args.Location.Name, args.GetCurrentValue(), args.Value));

			// Actually sets the value.
			args.ProceedSetValue();
		}
	}
}
